/* 
 * File:   codegenerator.h
 * Author: Kamil Chaber
 */

#ifndef GENERATOR_H
#define	GENERATOR_H

#include <fstream>
#include <sstream>
#include "symboltable/symboltable.h"

using namespace std;

class CodeGenerator {
private:
    SymbolTable& symbolTable;
    stringstream generatedASM;
        
    /**
     * Get the representation of the symbol table record.
     * Possible values (${lexem} evaluates to the record lexem):
     * - number: #${lexem} known as immediate addressing
     * - variable: ${lexem} known as direct addressing 
     * - reference: *${lexem} known as intermediate addressing
     * @param leftRec
     * @return 
     */
    string getElementRepresentation(SymbolTableRecord& leftRec);

    /**
     * Returns the operation type based on the record type (almost it is the left side record)
     * Possible values:
     * - "i": integer
     * - "r": real
     * @param leftRec
     * @return 
     */
    string getOperationType(SymbolTableRecord& leftRec);
    
    /**
     * For the given pair of records it checks their types consistence.
     * If types are consistent, then it returns <code>EMPTY_INT_VALUE<code>.
     * If types are not consistent, then it generates types conversion and returns
     * the index of the temporary variable holding the result of the conversion.
     * Always converts the right value to be consistent with the left one
     * @param leftRec
     * @param rightRec
     * @return 
     */
    int prepareTypeConversionIfNeeded(SymbolTableRecord& leftRec, SymbolTableRecord& rightRec);  
    
    /**
     * Creates new temporary variable, storing the result of the operation,
     * which type is set as a "operationType" parameter
     */
    int createTemporaryVariable(string operationType);
public:
    CodeGenerator(SymbolTable& symbolTable);

    /**
     * Generates jump to the specified label
     * @param toLabelName
     */
    void generateJump(string toLabelName);
    
    /**
     * Generates new label
     * @param labelName
     */
    void generateLabel(string labelName);
    
    /**
     * Generates assignment operation: (mov instruction)
     * @param lIndex
     * @param rIndex
     */
    void generateAssignment(int lIndex, int rIndex);
    
    /**
     * Generates new arithmetic operation: (add, sub, mul, div)
     * @param lIndex
     * @param rIndex
     * @param opType
     * @return 
     */
    int generateArithmeticOperation(int lIndex, int rIndex, ArithmeticOperationType opType);
    
    /**
     * Generates conversion to the negative number.
     * Returns an index of the temp variable holding the negation result
     * @param termIndex
     * @return 
     */
    int generateTermNegation(int termIndex);
    
    
    void generateWriteProc(int expressionIndex);
    
    /**
     * Generates the exit statement
     */
    void generateExit();
    
    /**
     * Saves current generation to the file
     * @param outputFileName
     */
    void createASMFile(const char* outputFileName);
    
    string toString();
    
    virtual ~CodeGenerator();
};

#endif	/* GENERATOR_H */

